package com.ksd.web.controller.system;

import java.io.File;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ksd.common.annotation.Log;
import com.ksd.common.config.PlayDataConfig;
import com.ksd.common.core.controller.BaseController;
import com.ksd.common.core.domain.AjaxResult;
import com.ksd.common.core.page.TableDataInfo;
import com.ksd.common.enums.BusinessType;
import com.ksd.common.utils.DateUtils;
import com.ksd.common.utils.StringUtils;
import com.ksd.common.utils.file.FileUploadUtils;
import com.ksd.common.utils.poi.ExcelUtil;
import com.ksd.quartz.util.TaskConstans;
import com.ksd.system.domain.SysVersion;
import com.ksd.system.service.ISysOperLogService;
import com.ksd.system.service.ISysVersionService;
import com.ksd.web.controller.bean.FileNode;
import com.ksd.web.controller.bean.UploadFileObjec;
import com.ksd.web.controller.tool.ZipFileFinderFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ksd.system.domain.SysData;
import com.ksd.system.service.ISysDataService;
import org.springframework.web.multipart.MultipartFile;

import static com.ksd.web.controller.system.SysIndexController.OSChecker;

/**
 * 内容导入Controller
 * 
 * @author y.wu
 * @date 2025-04-24
 */
@RestController
@RequestMapping("/system/sysData")
public class SysDataController extends BaseController
{
    @Autowired
    private ISysDataService sysDataService;

    @Autowired
    private ISysVersionService sysVersionService;
    @Autowired
    private ISysOperLogService sysOperLogService;
    /**
     * 查询内容导入列表
     */
    @PreAuthorize("@ss.hasPermi('system:sysData:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysData sysData)
    {
        startPage();
        List<SysData> list = sysDataService.selectSysDataList(sysData);
        return getDataTable(list);
    }

    /**
     * 导出内容导入列表
     */
    @PreAuthorize("@ss.hasPermi('system:sysData:export')")
    @Log(title = "内容导入", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysData sysData)
    {
        List<SysData> list = sysDataService.selectSysDataList(sysData);
        ExcelUtil<SysData> util = new ExcelUtil<SysData>(SysData.class);
        util.exportExcel(response, list, "内容导入数据");
    }

    /**
     * 获取内容导入详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:sysData:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(sysDataService.selectSysDataById(id));
    }

    /**
     * 新增内容导入
     */
    @PreAuthorize("@ss.hasPermi('system:sysData:add')")
    @Log(title = "内容导入", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SysData sysData)
    {

        return toAjax(sysDataService.insertSysData(sysData));
    }
    @GetMapping("/files")
    public AjaxResult getFiles() {
        // 指定目录路径
//        String rootPath = "C:\\Users\\wuyun\\Desktop";
        String rootPath = PlayDataConfig.getSynchPath();
        logger.info("获取USB硬盘内的文件目录: "+rootPath);
        File rootDirectory = new File(rootPath);
        List<FileNode> nodes = new ArrayList<>();
        if (rootDirectory.exists() && rootDirectory.isDirectory()) {
            for (File file : rootDirectory.listFiles()) {
                String name = file.getName();
                FileNode node = new FileNode();
                String string = UUID.randomUUID().toString();
                node.setId(string);
                node.setName(file.getName());
                node.setPath(file.getAbsolutePath());
                node.setLeaf(!file.isDirectory());
                nodes.add(node);
            }
        }
        return AjaxResult.success(nodes);
    }

    @PostMapping("/filesByPath")
    public AjaxResult getFilesByPath(@Validated @RequestBody FileNode fileNode) {
        System.out.println("path: "+fileNode.getPath());
        File directory = new File(fileNode.getPath());
        List<FileNode> nodes = new ArrayList<>();
        if (directory.exists() && directory.isDirectory()) {
            for (File file : directory.listFiles()) {
                String name = file.getName();
                FileNode node = new FileNode();
                String string = UUID.randomUUID().toString();
                node.setId(string);
                node.setName(file.getName());
                node.setPath(file.getAbsolutePath());
                node.setLeaf(!file.isDirectory());
                nodes.add(node);
            }
        }
        return AjaxResult.success(nodes);
    }

    @GetMapping("/checkUsbExist")
    public AjaxResult checkUsbExist(){

        String result = OSChecker();
        System.out.println("判断系统result: "+result);
        if (result.equals("Windows")){
            //默认windows都弹框导入文件
            return AjaxResult.success("当前运行环境是Windows系统,模拟检测出存在USB插入",true);
        }else if (result.equals("Linux")) {
            //执行服务器上的脚本文件,获取脚本结果
            String usbFilePath = PlayDataConfig.getDownloadPath();
            File file = new File(usbFilePath);
            if (!file.exists() || !file.isDirectory()) {
                logger.info("未检测出有U盘挂载,该指定文件路径不存在:"+file.getAbsolutePath());
                return AjaxResult.success("未检测出服务器上有挂载U盘",false);
            }
            int length = file.listFiles().length;
            if (length != 0){
                logger.info("已检测出有U盘挂载,文件挂载路径:"+file.getAbsolutePath());
                logger.info("该目录下存在的文件个数:"+length);
                //存在,判断系统首页是否有弹框显示,如果没有首页需弹框显示,
                return AjaxResult.success("已检测出存在USB插入",true);
            } else {
                logger.info("未检测出有U盘挂载");
                return AjaxResult.success("挂载的U盘下未检测到可用文件",false);
            }
        }else if (result.equals("Unknown")){
            logger.error("未检测出系统运行环境");
            return AjaxResult.success("未检测出系统的运行环境",false);
        }else{
            return AjaxResult.success("result:"+result,false);
        }
    }
    public static final String synch_zip_file = ".zip";
    @PostMapping("/uploadZip")
    public AjaxResult startUpload(@Validated @RequestBody UploadFileObjec uploadFileObjec) {

        List<String> filePaths = uploadFileObjec.getFilePaths();
        Set<String> channelFilePath = new HashSet<>();
        // 统计所有文件数量,该路径已经被算过,只存在具体的文件,没有文件夹
        for (String filePath : filePaths) {
            File directory = new File(filePath);
            if (directory.isDirectory()){
                channelFilePath = findFilesInSubdirectories(directory,channelFilePath);
            }else{
//                if (FileUploadUtils.isAllowedExtension(directory.getName(), TaskConstans.synch_file_name)){
                if(directory.getName().endsWith(synch_zip_file)){
                    //将文件夹下的所有文件都复制上传
                    channelFilePath.add(directory.getAbsolutePath());
                }
            }
        }

        if (channelFilePath.size() != 1){
             return error("当前内容导入选择的文件个数:"+channelFilePath.size()+",默认有且只有一个,请重新选择内容压缩包");
        }

        Iterator<String> iterator = channelFilePath.iterator();
        String filePath = iterator.next();
        File file = new File(filePath);
        if (file.exists()){
            String name = file.getName();
            if (!name.endsWith(synch_zip_file)){
                return error("当前内容导入选择的文件格式不正确!");
            }
        }
        //将压缩包文件入库,这里目的文件已经是nginx配置的目录文件下了,直接截取获取映射地址即可
        SysData sysData = new SysData();
        sysData.setName(file.getName());
        sysData.setSynchUrl(filePath);
        //获取映射文件地址
        String substring = filePath.substring(PlayDataConfig.getSynchPath().length());
        filePath = PlayDataConfig.getMappedPath()+File.separator+substring;
        sysData.setUrl(PlayDataConfig.getCloudDownService()+filePath);
        sysDataService.insertSysData(sysData);
        return success();
    }

    /**
     * 递归查找指定目录及其子目录下的所有文件  统计上传文件总个数
     * @param directory 要查找的目录
     */
    public static Set<String> findFilesInSubdirectories(File directory, Set<String> channelFilePath) {
        // 检查目录是否存在且为目录
        if (directory.exists() && directory.isDirectory()) {
            // 获取目录下的所有文件和子目录
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isFile()) {
                        // 如果是文件，打印文件的绝对路径
//                        System.out.println("找到文件: " + file.getAbsolutePath());
//                        if (FileUploadUtils.isAllowedExtension(file.getName(), TaskConstans.synch_file_name)){
                        if (file.getName().endsWith(synch_zip_file)){
                            //将文件夹下的所有文件都复制上传
//                            count++;
                            channelFilePath.add(file.getAbsolutePath());
                        }
                    } else if (file.isDirectory()) {
                        // 如果是子目录，递归调用该方法
                        channelFilePath = findFilesInSubdirectories(file,channelFilePath);
                    }
                }
            }
        } else {
            System.out.println("指定的路径不是一个有效的目录。"+directory.getAbsolutePath());
        }
        return channelFilePath;
    }
    /**
     * 导入数据
     */
    @PostMapping("/uploadFile")
    public AjaxResult uploadDataZipFile(MultipartFile file, HttpServletRequest request) throws Exception
    {
        String fileType = request.getParameter("fileType");
        System.out.println("上传文件,内容分类:"+fileType+"============="+file.getOriginalFilename());
        String dataPath = File.separator+"playdata_upload_data"+File.separator+ DateUtils.dateTimeNow();
        String synchFilePath = PlayDataConfig.getSynchPath() +  dataPath;
        String mapperFilePath = PlayDataConfig.getMappedPath() +  dataPath;
        String importPath = synchFilePath; //文件上传到指定目录下,即nginx配置下的目录,也是该压缩包在服务器上真实地址
        System.out.println("设置的文件上传地址:"+importPath);
        String zipFilePath = FileUploadUtils.upload(importPath, file);
        System.out.println("=================================压缩包上传到服务器的路径filePath:"+zipFilePath);
        String endFilePath = zipFilePath.substring(synchFilePath.length(), zipFilePath.length());
        System.out.println("endFilePath:"+endFilePath);
        System.out.println("设置的nginx配置下的地址:"+mapperFilePath);
        mapperFilePath = mapperFilePath+File.separator+endFilePath;
        System.out.println("mapper:"+mapperFilePath);
        File zipFile = new File(zipFilePath);
        System.out.println(file.getName()+"==============="+file.getOriginalFilename()+"&&&&&&&&&&&&"+zipFile.getName());
        System.out.println("解析上传目录的文件的所有文件,进行数据录入,可能存在电影,音乐");
        SysData sysData = new SysData();
        sysData.setName(zipFile.getName());
        sysData.setStatus("0");
        sysData.setUrl(PlayDataConfig.getCloudDownService()+mapperFilePath);//将压缩包解压后的地址映射地址,能够通过浏览器直接访问到
        sysData.setSynchUrl(zipFilePath);//压缩包地址
        sysData.setSynchFlag("0");//同步标识  0 表示未同步  1表示已同步
        sysData.setFileType(fileType);
        sysDataService.insertSysData(sysData);
        List<SysVersion> sysVersions = sysVersionService.selectSysVersionList(new SysVersion());
        for (SysVersion version : sysVersions) {
            version.setDataFlag("0");
            sysVersionService.updateSysVersion(version);
        }
        sysOperLogService.insertOperlogSuccess("数据导入模块上传压缩包成功,压缩包地址:"+sysData.getSynchUrl()+",数据同步映射地址:"+sysData.getUrl());
        return AjaxResult.success("文件上传成功");
    }
    /**
     * 修改内容导入
     */
    @PreAuthorize("@ss.hasPermi('system:sysData:edit')")
    @Log(title = "内容导入", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SysData sysData)
    {
        return toAjax(sysDataService.updateSysData(sysData));
    }

    /**
     * 删除内容导入
     */
    @PreAuthorize("@ss.hasPermi('system:sysData:remove')")
    @Log(title = "内容导入", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        for (Long id : ids) {
            SysData sysData = sysDataService.selectSysDataById(id);
            String synchUrl = sysData.getSynchUrl();
            File synchFile = new File(synchUrl);
            System.out.println("synchUrl:"+synchUrl);
            if (synchFile.exists()) {
//                boolean delete = synchFile.delete();
//                System.out.println("删除同步内容压缩包:"+delete);
            }
            sysDataService.deleteSysDataById(id);
            sysOperLogService.insertOperlogSuccess("删除内容同步记录:"+sysData.getName()+"内容文件映射地址:"+sysData.getUrl());
        }
        return success();
    }
}
